/**
 *====================================================
 * 文件名称: FinanceBulkstockNoticeActionApiImpl.java
 * 修订记录：
 * No    日期				作者(操作:具体内容)
 * 1.    2015年10月22日			chenxy(创建:创建文件)
 *====================================================
 * 类描述：(说明未实现或其它不应生成javadoc的内容)
 */
package com.yuexunit.finance.project.action.v1;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yuexunit.core.BusinessException;
import com.yuexunit.core.ConfigPropertites;
import com.yuexunit.finance.bulkstock.entity.BulkstockInfoEntity;
import com.yuexunit.finance.common.httpclient.HttpClientHelper;
import com.yuexunit.finance.common.util.BeanUtils;
import com.yuexunit.finance.common.util.CollectionUtils;
import com.yuexunit.finance.common.util.DateUtils;
import com.yuexunit.finance.common.util.LongUtils;
import com.yuexunit.finance.context.FinanceBaseAction;
import com.yuexunit.finance.context.FinanceConstant;
import com.yuexunit.finance.context.FinanceLetterBlockingQueue;
import com.yuexunit.finance.context.FinanceSessionContext;
import com.yuexunit.finance.member.entity.EnterpriseEntity;
import com.yuexunit.finance.member.entity.LogisticsCompanyEntity;
import com.yuexunit.finance.member.service.LogisticsCompanyService;
import com.yuexunit.finance.project.action.v1.dto.BulkstockCastor;
import com.yuexunit.finance.project.action.v1.dto.BulkstockNoticeCastor;
import com.yuexunit.finance.project.action.v1.dto.FinanceProcessCastor;
import com.yuexunit.finance.project.action.v1.model.output.DeliveryNoticeDetail;
import com.yuexunit.finance.project.action.v1.model.output.DeliveryNoticeLineInfo;
import com.yuexunit.finance.project.action.v1.model.output.HandleSuitcaseResult;
import com.yuexunit.finance.project.action.v1.model.output.RecieveNoticeDetail;
import com.yuexunit.finance.project.action.v1.model.output.RecieveNoticeInventory;
import com.yuexunit.finance.project.action.v1.model.output.SupervisionNoticeDetail;
import com.yuexunit.finance.project.action.v1.model.output.SupervisionNoticeLineInfo;
import com.yuexunit.finance.project.action.v1.model.output.TransportNoticeDetail;
import com.yuexunit.finance.project.action.v1.model.output.TransportNoticeLineInfo;
import com.yuexunit.finance.project.entity.ContainerBulkstockEntity;
import com.yuexunit.finance.project.entity.ContainerBulkstockHistoryEntity;
import com.yuexunit.finance.project.entity.ContainerInventoryEntity;
import com.yuexunit.finance.project.entity.ContainerInventoryHistoryEntity;
import com.yuexunit.finance.project.entity.DeliveryNoticeEntity;
import com.yuexunit.finance.project.entity.FinanceApplicationEntity;
import com.yuexunit.finance.project.entity.FinanceBulkstockEntity;
import com.yuexunit.finance.project.entity.FinanceContainerLogEntity;
import com.yuexunit.finance.project.entity.FinanceProcessDetailEntity;
import com.yuexunit.finance.project.entity.FinanceProcessEntity;
import com.yuexunit.finance.project.entity.PickupApplicationEntity;
import com.yuexunit.finance.project.entity.RecieveNoticeEntity;
import com.yuexunit.finance.project.entity.RecieveNoticeInventoryEntity;
import com.yuexunit.finance.project.entity.SupervisionNoticeEntity;
import com.yuexunit.finance.project.entity.TallyingEntity;
import com.yuexunit.finance.project.entity.TransportNoticeEntity;
import com.yuexunit.finance.project.entity.lexicon.AbnormalStateEnum;
import com.yuexunit.finance.project.entity.lexicon.ApplicationStateEnum;
import com.yuexunit.finance.project.entity.lexicon.BadassetsStateEnum;
import com.yuexunit.finance.project.entity.lexicon.BulkstockSourceEnum;
import com.yuexunit.finance.project.entity.lexicon.ExchangeStatusEnum;
import com.yuexunit.finance.project.entity.lexicon.FinanceStateEnum;
import com.yuexunit.finance.project.entity.lexicon.NoticeInformStateEnum;
import com.yuexunit.finance.project.entity.lexicon.NoticeStateEnum;
import com.yuexunit.finance.project.entity.lexicon.PickupMethodEnum;
import com.yuexunit.finance.project.entity.lexicon.ProductTypeEnum;
import com.yuexunit.finance.project.entity.lexicon.SupervisionStateEnum;
import com.yuexunit.finance.project.entity.lexicon.TallyingStateEnum;
import com.yuexunit.finance.system.action.v1.dto.SendLetterMessage;
import com.yuexunit.inject.ComponentFactory;
import com.yuexunit.inject.annotation.Implements;
import com.yuexunit.page.PageCriteria;
import com.yuexunit.page.PageList;
import com.yuexunit.persist.PersistUtil;
import com.yuexunit.persist.annotation.Transactional;
import com.yuexunit.util.DateUtil;

/**
 * @ClassName: FinanceBulkstockNoticeActionApiImpl
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author chenxy
 * @date 2015年10月22日 下午3:25:46
 */
@Implements(FinanceBulkstockNoticeActionApi.class)
public class FinanceBulkstockNoticeActionApiImpl extends FinanceBaseAction implements FinanceBulkstockNoticeActionApi {
	private FinanceApplicationActionApi financeApplicationActionApi = ComponentFactory.loadClass(FinanceApplicationActionApi.class);
	
	private String tmp = "客户(%s)融资(%s)目前处于(%s)环节，请及时处理！";

	private static Logger logger = LoggerFactory.getLogger(FinanceBulkstockNoticeActionApiImpl.class);

	@Transactional
	@Override
	public String createSupervisionNotice(Long financeId, String noticeContent) {
		if (supervisionNoticeService.inquireFinanceIdSupervisionNotice(financeId) != null) {
			throw new BusinessException("已下发监管通知书");
		}
		SupervisionNoticeEntity entity = BulkstockNoticeCastor.fromSupervisionNotice(financeId, noticeContent);
		Long supervisionNoticeId = supervisionNoticeService.createSupervisionNotice(entity);

		FinanceApplicationEntity financeEntity = financeApplicationService.inquireFinanceApplicationEntity(financeId);
		financeEntity.setSupervisionNoticeId(supervisionNoticeId);
		financeApplicationService.renovateFinanceApplication(financeEntity);

		// 项目动态
		FinanceProcessEntity financeProcessEntity = FinanceProcessCastor.fromSupervisionNoticeProcess(financeId, financeEntity.getFinanceNumber(), supervisionNoticeId);
		financeProcessService.createFinanceProcess(financeProcessEntity);
		return supervisionNoticeId.toString();
	}

	@Transactional
	@Override
	public void updateSupervisionNotice(Long supervisionNoticeId, String noticeContent) {
		SupervisionNoticeEntity entity = supervisionNoticeService.inquireSupervisionNotice(supervisionNoticeId);
		entity.setNoticeContent(noticeContent);
		if (NoticeInformStateEnum.REFUSE == entity.getNoticeState()) {
			entity.setNoticeState(NoticeInformStateEnum.UNCONFIRM);
		}
		supervisionNoticeService.updateSupervisionNotice(entity);
	}

	@Transactional
	@Override
	public void consentSupervisionNotice(Long supervisionNoticeId) {
		SupervisionNoticeEntity entity = supervisionNoticeService.inquireSupervisionNotice(supervisionNoticeId);
		entity.setConfirmAccount(FinanceSessionContext.getAccountFullName());
		entity.setConfirmAccountId(FinanceSessionContext.getAccountId());
		entity.setConfirmDateTime(new Date());
		entity.setNoticeState(NoticeInformStateEnum.CONFIRM);
		supervisionNoticeService.updateSupervisionNotice(entity);
	}

	@Transactional
	@Override
	public void opposeSupervisionNotice(Long supervisionNoticeId) {
		SupervisionNoticeEntity entity = supervisionNoticeService.inquireSupervisionNotice(supervisionNoticeId);
		entity.setNoticeState(NoticeInformStateEnum.REFUSE);
		supervisionNoticeService.updateSupervisionNotice(entity);
	}

	@Override
	public SupervisionNoticeDetail inquireSupervisionNoticeDetail(Long supervisionNoticeId) {
		SupervisionNoticeEntity entity = supervisionNoticeService.inquireSupervisionNotice(supervisionNoticeId);
		return BulkstockNoticeCastor.toSupervisionNoticeDetail(entity);
	}

	@Override
	public SupervisionNoticeDetail inquireFinanceSupervisionNotice(Long financeId) {
		SupervisionNoticeEntity entity = supervisionNoticeService.inquireFinanceIdSupervisionNotice(financeId);
		return BulkstockNoticeCastor.toSupervisionNoticeDetail(entity);
	}

	@Override
	public PageList<SupervisionNoticeLineInfo> inquireSupervisionNoticePageList(Long financeId, String financeNumber, Integer noticeState, PageCriteria page) {
		PageList<SupervisionNoticeEntity> pageList = supervisionNoticeService.inquireSupervisionNoticePageList(financeId, financeNumber, noticeState, page);
		PageList<SupervisionNoticeLineInfo> resultList = new PageList<SupervisionNoticeLineInfo>(page, pageList.getTotalRecordCount());
		for (SupervisionNoticeEntity entity : pageList) {
			resultList.add(BulkstockNoticeCastor.toSupervisionNoticeLineInfo(entity));
		}
		return resultList;
	}

	// ====================================================================================================================================================//
	// 更新通知收获数量
	private void adjustFinanceBulkstockRecieve(Long bulkstockId, BigDecimal add, BigDecimal subtract) {
		FinanceBulkstockEntity bulkstock = financeBulkstockService.inquireFinanceBulkstock(bulkstockId);
		bulkstock.setRecieve(bulkstock.getRecieve().add(add).subtract(subtract));
		if (bulkstock.getRecieve().intValue() > bulkstock.getQuantity().intValue()) {
			throw new BusinessException("收货数量大于融资申请数量");
		}
		financeBulkstockService.renovateFinanceBulkstock(bulkstock);
	}

	@Transactional
	@Override
	public String createRecieveNotice(Long financeId, Long logisticsCompanyId, String logisticsCompanyName, String noticeRemark, Long[] bulkstockIds, BigDecimal[] quantities, String[] caseSizes, Integer[] caseQuantities) {
		FinanceApplicationEntity financeEntity = financeApplicationService.inquireFinanceApplicationEntity(financeId);
		RecieveNoticeEntity recieveNoticeEntity = BulkstockNoticeCastor.fromRecieveNotice(financeEntity, logisticsCompanyId, logisticsCompanyName, noticeRemark, bulkstockIds);
		Long recieveNoticeId = recieveNoticeService.createRecieveNotice(recieveNoticeEntity);

		List<RecieveNoticeInventoryEntity> detailEntities = BulkstockCastor.fromRecieveNoticeDetail(recieveNoticeId, financeId, bulkstockIds, quantities, caseSizes, caseQuantities);
		for (RecieveNoticeInventoryEntity entity : detailEntities) {
			recieveNoticeInventoryService.createRecieveNoticeInventory(entity);
			// 更新通知收获数量
			adjustFinanceBulkstockRecieve(entity.getBulkstockId(), entity.getQuantity(), BigDecimal.ZERO);
		}
		// 项目状态更新
		financeEntity.setFinanceState(FinanceStateEnum.WAIT_INSPECTION);
		financeApplicationService.renovateFinanceApplication(financeEntity);
		// 发送消息
		FinanceLetterBlockingQueue.putEnterpriseFinanceLetter(getFinanceEnterpriseId(financeId), "收货通知", "finance.recieve.notice", recieveNoticeEntity.getRecieveNoticeNumber());
		// 项目动态
		FinanceProcessEntity financeProcessEntity = FinanceProcessCastor.fromFinanceRecieveNoticeProcess(recieveNoticeEntity, detailEntities);
		financeProcessService.createFinanceProcess(financeProcessEntity);
		return recieveNoticeId.toString();
	}

	@Override
	@Transactional
	public void createWareHouseRecieveNotice(Long financeId, String enterpriseId, Date bookingTime, String protocolNo,
			String wareHouseId, BigDecimal minControlValue, BigDecimal warningValue, BigDecimal warningRate,
			Long[] bulkstockIds, BigDecimal[] quantities) {
		FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(financeId);
		EnterpriseEntity enterprise = enterpriseService.inquireEnterprise(finance.getEnterpriseId());

		Map<String, String> params = new HashMap<>();

		StringBuffer quantitys = new StringBuffer();
		StringBuffer weights = new StringBuffer();
		StringBuffer volumes = new StringBuffer();
		StringBuffer bulkstockNames = new StringBuffer();
		StringBuffer bulkstockNumbers = new StringBuffer();
		StringBuffer specifications = new StringBuffer();
		StringBuffer bulkstockInfoIds = new StringBuffer();
		StringBuffer bulkstockIdss = new StringBuffer();
		StringBuffer bulkstockPrices = new StringBuffer();
		StringBuffer bulkstockValuations = new StringBuffer();
		StringBuffer units = new StringBuffer();
		for (int i = 0; i < bulkstockIds.length; i++) {
			FinanceBulkstockEntity fbe = financeBulkstockService.inquireFinanceBulkstock(bulkstockIds[i]);
			weights.append(fbe.getWeight()).append(",");
			bulkstockNames.append(fbe.getBulkstockName()).append(",");
			bulkstockNumbers.append(fbe.getBulkstockNumber()).append(",");
			specifications.append(fbe.getSpecification()).append(",");
			bulkstockInfoIds.append(fbe.getBulkstockInfoId()).append(",");
			quantitys.append(quantities[i]).append(",");
			bulkstockPrices.append(fbe.getBulkstockPrice()).append(",");
			bulkstockIdss.append(bulkstockIds[i]).append(",");
			units.append(fbe.getUnit()).append(",");
			bulkstockValuations.append(fbe.getBulkstockPrice().multiply(fbe.getWeight())).append(",");

			if (fbe.getVolume() != null) {
				volumes.append(fbe.getVolume()).append(",");
			} else {
				volumes.append(BigDecimal.ZERO).append(",");
			}
			fbe.setRecieve(quantities[i]);
			//			financeBulkstockService.updateFinanceBulkstockEntity(fbe);
		}
		if (volumes.length() > 0) {
			volumes.deleteCharAt(volumes.length() - 1);
		}
		if (units.length() > 0) {
			units.deleteCharAt(units.length() - 1);
		}
		if (bulkstockValuations.length() > 0) {
			bulkstockValuations.deleteCharAt(bulkstockValuations.length() - 1);
		}
		if (weights.length() > 0) {
			weights.deleteCharAt(weights.length() - 1);
		}
		if (bulkstockNames.length() > 0) {
			bulkstockNames.deleteCharAt(bulkstockNames.length() - 1);
		}
		if (bulkstockNumbers.length() > 0) {
			bulkstockNumbers.deleteCharAt(bulkstockNumbers.length() - 1);
		}
		if (bulkstockPrices.length() > 0) {
			bulkstockPrices.deleteCharAt(bulkstockPrices.length() - 1);
		}
		if (specifications.length() > 0) {
			specifications.deleteCharAt(specifications.length() - 1);
		}
		if (bulkstockInfoIds.length() > 0) {
			bulkstockInfoIds.deleteCharAt(bulkstockInfoIds.length() - 1);
		}
		if (quantitys.length() > 0) {
			quantitys.deleteCharAt(quantitys.length() - 1);
		}
		if (bulkstockIdss.length() > 0) {
			bulkstockIdss.deleteCharAt(bulkstockIdss.length() - 1);
		}

		if (null != minControlValue) {
			params.put("min_control_value", minControlValue.toString());
		}

		if (null != warningRate) {
			params.put("warning_rate", warningRate.toString());
		}

		if (null != minControlValue && null != warningRate) {
			params.put("warning_value", (minControlValue.multiply((warningRate.add(FinanceConstant.HUNDRED)).divide(FinanceConstant.HUNDRED))).toString());
		}
		params.put("financeId", financeId.toString());
		params.put("finance_no", finance.getFinanceNumber());
		params.put("warehouseId", wareHouseId);
		params.put("register_date", DateUtil.nowDate());
		//企业信息
		params.put("custCode", "CU1705030001");
		params.put("enterpriseId", enterpriseId);
		params.put("custId", enterprise.getEnterpriseId().toString());
		params.put("enterprise_name", enterprise.getEnterpriseName());
		params.put("enterprise_short_name", enterprise.getEnterpriseShortName());
		params.put("nature", enterprise.getNature());
		params.put("business_type", enterprise.getBusinessType());
		params.put("contact_address", enterprise.getContactAddress());
		params.put("zip_code", enterprise.getZipCode());
		params.put("contact_number", enterprise.getContactNumber());
		params.put("legal_person", enterprise.getLegalPerson());
		params.put("business_licience", enterprise.getBusinessLicence());
		//货物信息
		params.put("bulkstock_Id", bulkstockIdss.toString());
		params.put("unit", units.toString());
		params.put("quantity", quantitys.toString());
		params.put("weight", weights.toString());
		params.put("volume", volumes.toString());
		params.put("bulkstock_name", bulkstockNames.toString());
		params.put("bulkstock_number", bulkstockNumbers.toString());
		params.put("specificition", specifications.toString());
		params.put("bulkstock_info_id", bulkstockInfoIds.toString());
		params.put("unit_price", bulkstockPrices.toString().toString());
		params.put("total_price", bulkstockValuations.toString());

		logger.info("params:" + params);
		String url = ConfigPropertites.getProperties("finance.saveProtocolInfo.service");
		String responseText = HttpClientHelper.post(url, params);
		if (null == responseText) {
			throw new BusinessException("通知失败！");
		}
		finance.setFinanceState(FinanceStateEnum.WAIT_INSPECTION);
		financeApplicationService.updateFinanceApplication(finance);
	}

	@Transactional
	@Override
	public void createWareHouseInventory(Long financeId, String warehouseName[], String[] wareHouseNumbers, Long[] bulkstockInfoIds, BigDecimal[] quantitys, BigDecimal[] weights, BigDecimal[] volumes, String[] location_names, String[] location_areas, String[] customerId, String[] location_id, String[] warehouseId) {
		FinanceApplicationEntity finance = this.financeApplicationService.inquireFinanceApplicationEntity(financeId);
		if ((bulkstockInfoIds == null) || (bulkstockInfoIds.length <= 0)) {
			throw new BusinessException("货物不允许为空！");
		}
		for (int i = 0; i < wareHouseNumbers.length; ++i) {
			if (finance.getEnterpriseId() != Long.parseLong(customerId[i])) {
				throw new BusinessException("入库单号" + wareHouseNumbers[i] + "不属于客户" + finance.getEnterpriseName() + "!");
			}
			
			ContainerInventoryEntity exist = containerInventoryService.inquireContainerInventory("", wareHouseNumbers[i]);
			if (null != exist) {
				throw new BusinessException("入库单号" + wareHouseNumbers[i] + "已存在！");
			}
			
			ContainerInventoryEntity cie = new ContainerInventoryEntity();
			cie.setAdjustment(BigDecimal.ZERO);
			cie.setWarehouseName(warehouseName[i]);
			cie.setCaseNumber(wareHouseNumbers[i]);
			cie.setContainerSource(BulkstockSourceEnum.FINANCE);
			cie.setAbnormal(Boolean.TRUE);
			cie.setAbnormalState(AbnormalStateEnum.UNKNOWN);
			cie.setTallyingState(Boolean.TRUE);
			cie.setType(Integer.valueOf(1));
			cie.setTallyDateTime(DateUtil.now());
			cie.setFinanceId(finance.getFinanceId());
			cie.setFinanceNumber(finance.getFinanceNumber());
			cie.setEnterpriseId(finance.getEnterpriseId());
			cie.setEnterpriseName(finance.getEnterpriseName());
			cie.setHarborDateTime(DateUtil.now());
			cie.setHarborState(Boolean.TRUE);
			cie.setEnabled(Boolean.TRUE);
			cie.setSupervisionState(SupervisionStateEnum.DELIVERY_SURE);
			cie.setReceiveConfirmCreateTime(DateUtil.now());
			cie.setRedeemState(Boolean.FALSE);
			cie.setDetainedState(Boolean.FALSE);
			cie.setBadassetsState(BadassetsStateEnum.UNKNOWN);
			cie.setLogisticsCompanyInfoId(0L);
			cie.setLocationArea(location_areas[i]);
			cie.setLocationName(location_names[i]);
			cie.setLocationId(location_id[i]);
			cie.setPickupQuantity(BigDecimal.ZERO);
			cie.setWarehouseId(warehouseId[i]);
			containerInventoryService.createContainerInventory(cie);

			List<FinanceBulkstockEntity> fbes = financeBulkstockService.inquireFinanceBulkstockList(financeId);
			FinanceBulkstockEntity fbe = fbes.get(0);
			ContainerBulkstockEntity cbe = new ContainerBulkstockEntity();
			BeanUtils.copyProperties(fbe, cbe, new String[0]);
			cbe.setInventoryId(cie.getInventoryId());
			cbe.setPlannedQuantity(quantitys[i]);
			cbe.setPlannedVolume(volumes[i]);
			cbe.setPlannedWeight(weights[i]);
			cbe.setQuantity(quantitys[i]);
			cbe.setBulkstockId(fbe.getBulkstockId());
			cbe.setVolume(volumes[i]);
			cbe.setWeight(weights[i]);
			cbe.setValuationQuantity(weights[i]);
//			fbe.setRecieve(fbe.getRecieve().add(cbe.getQuantity()));
			fbe.setRecieve(fbe.getQuantity());
			financeBulkstockService.updateFinanceBulkstockEntity(fbe);

			containerBulkstockService.createContainerBulkstock(cbe);
			
			//入库单加锁
			financeApplicationActionApi.lockWarehouseAndInbound(cie.getCaseNumber());
		}
		finance.setFinanceState(FinanceStateEnum.INSPECTIONED);
		financeApplicationService.updateFinanceApplication(finance);
		//消息推送-确认监管
		SendLetterMessage.sendLetterMessage("financeUnsupervise_1", String.format(tmp, finance.getEnterpriseName(), finance.getFinanceNumber(), "确认监管"));
	}

	@Override
	@Transactional
	public void refuseWareHouseReceiveNotice(Long financeId, Long[] bulkstockIds, BigDecimal[] quantities) {
		for (int i = 0; i < bulkstockIds.length; i++) {
			FinanceBulkstockEntity fbe = financeBulkstockService.inquireFinanceBulkstock(bulkstockIds[i]);
			fbe.setRecieve(fbe.getRecieve().subtract(quantities[i]));
			financeBulkstockService.updateFinanceBulkstockEntity(fbe);
		}
		FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(financeId);
		finance.setFinanceState(FinanceStateEnum.FIRSTCOMPLETE);
		financeApplicationService.updateFinanceApplication(finance);
	}

	@Transactional
	@Override
	public String createRecieveNoticeLogistics(Long[] bulkstockInfoIds, String[] originPlaces, BigDecimal[] quantities, BigDecimal[] weights, BigDecimal[] volumes, String bookingSpaceNumber) {
		RecieveNoticeEntity recieveNoticeEntity = new RecieveNoticeEntity();
		LogisticsCompanyService logisticsCompanyService = ComponentFactory.loadClass(LogisticsCompanyService.class);
		LogisticsCompanyEntity lc = logisticsCompanyService.inquireTenantLogisticsCompany(FinanceSessionContext.getAccountTenantId());
		recieveNoticeEntity.setBulkstockSource(BulkstockSourceEnum.LOGISTICS);
		recieveNoticeEntity.setLogisticsCompanyId(lc.getCompanyId());
		recieveNoticeEntity.setBookingSpaceNumber(bookingSpaceNumber);
		recieveNoticeEntity.setLogisticsCompanyName(lc.getCompanyName());
		Long recieveNoticeId = recieveNoticeService.createRecieveNotice(recieveNoticeEntity);
		for (int i = 0; i < bulkstockInfoIds.length; i++) {
			RecieveNoticeInventoryEntity entity = new RecieveNoticeInventoryEntity();
			BulkstockInfoEntity bulkstockInfo = bulkstockInfoService.inquireBulkstockInfo(bulkstockInfoIds[i]);
			String originPlace = CollectionUtils.getArrayIndexValue(originPlaces, i);
			BigDecimal weight = CollectionUtils.getArrayIndexValue(weights, i);
			BigDecimal quantity = CollectionUtils.getArrayIndexValue(quantities, i);
			BigDecimal volume = CollectionUtils.getArrayIndexValue(volumes, i);

			entity.setBulkstockInfoId(bulkstockInfo.getBulkstockInfoId());
			entity.setBulkstockCategoryId(bulkstockInfo.getBulkstockCategoryId());
			entity.setBulkstockNumber(bulkstockInfo.getBulkstockNumber());
			entity.setOriginPlace(originPlace);
			entity.setQuantity(quantity);
			entity.setVolume(volume);
			entity.setWeight(weight);
			entity.setRecieveNoticeId(recieveNoticeId);
			entity.setBulkstockName(bulkstockInfo.getBulkstockName());
			entity.setSpecification(bulkstockInfo.getSpecificationName());

			recieveNoticeInventoryService.createRecieveNoticeInventory(entity);
		}

		return recieveNoticeId.toString();
	}
	
	@Transactional
	@Override
	public void deleteReceivingTally(Long recieveNoticeId) {
		List<Long> noticeInventoryIds=financeApplicationService.inquireRecieveNoticeInventoryEntity(recieveNoticeId);
		List<Long> sList=null;
		if(noticeInventoryIds !=null && noticeInventoryIds.size()>0){
			for(Long noticeInventoryId:noticeInventoryIds){
				sList=new ArrayList<Long>();
				sList.add(noticeInventoryId);
				PersistUtil.delete(RecieveNoticeInventoryEntity.class, noticeInventoryId);
			}
		}
		
		PersistUtil.delete(RecieveNoticeEntity.class, recieveNoticeId);
		
		List<Long> tallyingIds=financeApplicationService.inquireTallyingEntity(recieveNoticeId);
		if(tallyingIds !=null && tallyingIds.size()>0){
			for(Long tallyingId:tallyingIds){
				PersistUtil.delete(TallyingEntity.class, tallyingId);
			}
		}
		if(sList !=null && sList.size() >0 ){
			for(Long  noticeInventoryId : sList){
				List<Long> bulkstockHistoryIds=financeApplicationService.inquireContainerBulkstockHistoryEntity(noticeInventoryId);
				if(bulkstockHistoryIds !=null && bulkstockHistoryIds.size()>0){
					for(Long bulkstockHistoryId:bulkstockHistoryIds){
						PersistUtil.delete(ContainerBulkstockHistoryEntity.class, bulkstockHistoryId);
					}
				}
			}
		}
		List<Long> inventoryHistoryIds=financeApplicationService.inquireContainerInventoryHistoryEntity(recieveNoticeId);
		if(inventoryHistoryIds !=null && inventoryHistoryIds.size()>0){
			for(Long inventoryHistoryId:inventoryHistoryIds){
				PersistUtil.delete(ContainerInventoryHistoryEntity.class, inventoryHistoryId);
			}
		}
	}
	@Transactional
	@Override
	public String createRepeatRecieveNotice(Long financeId, Long[] inventoryIds, Long logisticsCompanyId, String logisticsCompanyName, String noticeRemark) {
		
		FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(financeId);
		
		if (ProductTypeEnum.PROXY_SALE == finance.getProductType() || ProductTypeEnum.MANIFEST_PLEDGE == finance.getProductType() || ProductTypeEnum.PURCHASING_STORAGE == finance.getProductType()) {
			List<ContainerInventoryEntity> containers = containerInventoryService.inquireContainerInventoryList(inventoryIds);
			for (ContainerInventoryEntity cie : containers) {
				if (!financeId.equals(cie.getFinanceId())) {
					throw new BusinessException("再次理货的箱只能来源同一融资项目");
				}
				containerInventoryService.deleteContainerInventory(cie.getInventoryId());
				financeApplicationActionApi.unlockInbound(cie.getCaseNumber());
			}
			
			List<FinanceBulkstockEntity> fbes = financeBulkstockService.inquireFinanceBulkstockList(finance.getFinanceId());
			for (FinanceBulkstockEntity fbe : fbes) {
				fbe.setRecieve(BigDecimal.ZERO);
				financeBulkstockService.updateFinanceBulkstockEntity(fbe);
			}
			
			finance.setFinanceState(FinanceStateEnum.WAIT_INSPECTION);
			financeApplicationService.updateFinanceApplication(finance);
			return "0";
		} else {
			List<ContainerInventoryEntity> containers = containerInventoryService.inquireContainerInventoryList(inventoryIds);
			for (ContainerInventoryEntity cie : containers) {
				if (!financeId.equals(cie.getFinanceId())) {
					throw new BusinessException("再次理货的箱只能来源同一融资项目");
				}
				if (SupervisionStateEnum.ALREADY_REPORT != cie.getSupervisionState() || SupervisionStateEnum.UNKNOWN == cie.getSupervisionState()) {
					throw new BusinessException("只能对已上报的箱下发再次理货通知,箱号[" + cie.getCaseNumber() + "]-[" + cie.getSupervisionState().getValue() + "]");
				}
			}
			RecieveNoticeEntity recieveNotice = new RecieveNoticeEntity();
			recieveNotice.setBulkstockSource(BulkstockSourceEnum.REPEAT);
			recieveNotice.setFinanceId(finance.getFinanceId());
			recieveNotice.setFinanceNumber(finance.getFinanceNumber());
			recieveNotice.setEnterpriseId(finance.getEnterpriseId());
			recieveNotice.setEnterpriseName(finance.getEnterpriseName());
			recieveNotice.setLogisticsCompanyId(logisticsCompanyId);
			recieveNotice.setLogisticsCompanyName(logisticsCompanyName);
			recieveNotice.setNoticeRemark(noticeRemark);
			recieveNotice.setNoticeState(NoticeStateEnum.CONFIRMED);
			recieveNotice.setConfirmDateTime(DateUtils.now());
			recieveNotice.setConfirmAccountId(FinanceSessionContext.getAccountId());
			recieveNotice.setConfirmAccount(FinanceSessionContext.getAccountFullName());
			Long recieveNoticeId = recieveNoticeService.createRecieveNotice(recieveNotice);
			Map<Long, RecieveNoticeInventoryEntity> recieveBulkstocks = new HashMap<>();
			for (ContainerInventoryEntity cie : containers) {
				// 生成理货任务
				TallyingEntity tallying = new TallyingEntity();
				tallying.setRecieveNoticeId(recieveNoticeId);
				tallying.setFinanceId(recieveNotice.getFinanceId());
				tallying.setFinanceNumber(recieveNotice.getFinanceNumber());
				tallying.setEnterpriseId(recieveNotice.getEnterpriseId());
				tallying.setEnterpriseName(recieveNotice.getEnterpriseName());
				tallying.setLogisticsCompanyId(recieveNotice.getLogisticsCompanyId());
				tallying.setLogisticsCompanyName(recieveNotice.getLogisticsCompanyName());
				tallying.setLimitDate(DateUtil.nextDay(DateUtil.now()));
				tallying.setUserDefined(Boolean.FALSE);
				tallying.setTallyingState(TallyingStateEnum.WAIT_TALLY);
				tallyingService.createTallying(tallying);

				ContainerInventoryHistoryEntity container = new ContainerInventoryHistoryEntity();
				container.setInventoryId(cie.getInventoryId());
				container.setFinanceId(recieveNotice.getFinanceId());
				container.setFinanceNumber(recieveNotice.getFinanceNumber());
				container.setEnterpriseId(recieveNotice.getEnterpriseId());
				container.setEnterpriseName(recieveNotice.getEnterpriseName());
				container.setRecieveNoticeId(recieveNoticeId);
				container.setTallyingId(tallying.getTallyingId());
				container.setTallyingCompanyId(recieveNotice.getLogisticsCompanyId());
				container.setTallyingState(Boolean.FALSE);
				container.setWaybillNumber(cie.getWaybillNumber());
				container.setCaseNumber(cie.getCaseNumber());
				container.setCaseSize(cie.getCaseSize());
				container.setModel(cie.getModel());
				container.setDimension(cie.getDimension());
				container.setFacingSlip(cie.getFacingSlip());
				container.setFacingSlipNext(cie.getFacingSlipNext());
				containerInventoryHistoryService.createContainerInventory(container);

				List<ContainerBulkstockEntity> cbes = containerBulkstockService.inquireContainerBulkstockList(cie.getInventoryId());
				RecieveNoticeInventoryEntity recieveBulkstock = null;
				for (ContainerBulkstockEntity cbe : cbes) {
					FinanceBulkstockEntity financeBulkstock = financeBulkstockService.inquireFinanceBulkstock(cbe.getBulkstockId());
					recieveBulkstock = recieveBulkstocks.get(cbe.getBulkstockId());
					if (recieveBulkstock == null) {
						recieveBulkstock = new RecieveNoticeInventoryEntity();
						recieveBulkstock.setFinanceId(recieveNotice.getFinanceId());
						recieveBulkstock.setRecieveNoticeId(recieveNoticeId);
						recieveBulkstock.setRecieveNoticeNumber(recieveNotice.getRecieveNoticeNumber());
						recieveBulkstock.setBulkstockCategoryId(cbe.getBulkstockCategoryId());
						recieveBulkstock.setBulkstockInfoId(cbe.getBulkstockInfoId());
						recieveBulkstock.setBulkstockId(cbe.getBulkstockId());
						recieveBulkstock.setBulkstockName(cbe.getBulkstockName());
						recieveBulkstock.setBulkstockNumber(financeBulkstock.getBulkstockNumber());
						recieveBulkstock.setSpecification(cbe.getSpecification());
						recieveBulkstock.setOriginPlace(financeBulkstock.getOriginPlace());
						recieveBulkstock.setUnit(financeBulkstock.getUnit());
						recieveBulkstock.setQuantity(BigDecimal.ZERO);
						recieveBulkstock.setVolume(BigDecimal.ZERO);
						recieveBulkstock.setWeight(BigDecimal.ZERO);
						recieveBulkstock.setTallying(BigDecimal.ZERO);
						recieveBulkstock.setPlannedQuantity(BigDecimal.ZERO);
						recieveBulkstocks.put(recieveBulkstock.getBulkstockId(), recieveBulkstock);
						recieveNoticeInventoryService.createRecieveNoticeInventory(recieveBulkstock);
					}
					recieveBulkstock.setQuantity(recieveBulkstock.getQuantity().add(cbe.getQuantity()));
					if (recieveBulkstock.getVolume() != null && cbe.getVolume() != null) {
						recieveBulkstock.setVolume(recieveBulkstock.getVolume().add(cbe.getVolume()));
					}
					recieveBulkstock.setWeight(recieveBulkstock.getWeight().add(cbe.getWeight()));
					recieveNoticeInventoryService.renovateRecieveNoticeInventory(recieveBulkstock);

					// 计划箱货物信息
					ContainerBulkstockHistoryEntity cbhe = new ContainerBulkstockHistoryEntity();
					cbhe.setInventoryHistoryId(container.getInventoryHistoryId());
					cbhe.setContainerBulkstockId(cbe.getContainerBulkstockId());
					cbhe.setTallyingId(container.getTallyingId());
					cbhe.setNoticeInventoryId(recieveBulkstock.getNoticeInventoryId());
					cbhe.setFinanceId(container.getFinanceId());
					cbhe.setBulkstockId(recieveBulkstock.getBulkstockId());
					cbhe.setBulkstockCategoryId(recieveBulkstock.getBulkstockCategoryId());
					cbhe.setBulkstockInfoId(recieveBulkstock.getBulkstockInfoId());
					cbhe.setTrayNumber(cbe.getTrayNumber());
					cbhe.setBulkstockName(recieveBulkstock.getBulkstockName());
					cbhe.setSpecification(recieveBulkstock.getSpecification());
					cbhe.setUnit(recieveBulkstock.getUnit());
					cbhe.setPlannedQuantity(cbe.getQuantity());
					cbhe.setPlannedVolume(cbe.getVolume());
					cbhe.setPlannedWeight(cbe.getWeight());
					cbhe.setMeasurement(cbe.getMeasurement());
					cbhe.setBulkstockPrice(cbe.getBulkstockPrice());
					cbhe.setEvaluatePrice(cbe.getEvaluatePrice());
					cbhe.setFinancePrice(cbe.getFinancePrice());
					containerBulkstockHistoryService.createContainerBulkstock(cbhe);

					cie.setSupervisionState(SupervisionStateEnum.UNKNOWN); // 监管状态置为未上报
					containerInventoryService.renovateContainerInventory(cie);
				}
			}
			return recieveNoticeId.toString();
		}
		
	}

	@Transactional
	@Override
	public void updateRecieveNotice(Long recieveNoticeId, Long logisticsCompanyId, String logisticsCompanyName, String noticeRemark, Long[] recieveNoticeDetailIds, Long[] bulkstockIds, BigDecimal[] quantities, String[] caseSizes,
			Integer[] caseQuantities) {
		RecieveNoticeEntity persist = recieveNoticeService.inquireRecieveNoticeDetail(recieveNoticeId);
		persist.setLogisticsCompanyId(logisticsCompanyId);
		persist.setLogisticsCompanyName(logisticsCompanyName);
		persist.setNoticeRemark(noticeRemark);
		recieveNoticeService.updateRecieveNotice(persist);

		Set<Long> detailIds = CollectionUtils.convertSet(recieveNoticeDetailIds);
		List<RecieveNoticeInventoryEntity> detailPersists = recieveNoticeInventoryService.inquireRecieveNoticeInventoryList(recieveNoticeId);
		List<RecieveNoticeInventoryEntity> detailEntities = BulkstockCastor.fromRecieveNoticeDetail(recieveNoticeId, persist.getFinanceId(), bulkstockIds, quantities, caseSizes, caseQuantities);
		for (RecieveNoticeInventoryEntity p : detailPersists) {
			if (!detailIds.contains(p.getNoticeInventoryId())) {
				recieveNoticeInventoryService.deleteRecieveNoticeInventory(p.getNoticeInventoryId());
			}
			// 先扣减已存在的数量
			adjustFinanceBulkstockRecieve(p.getBulkstockId(), BigDecimal.ZERO, p.getQuantity());
		}
		for (int i = 0; i < detailEntities.size(); i++) {
			RecieveNoticeInventoryEntity entity = detailEntities.get(i);
			entity.setNoticeInventoryId(recieveNoticeDetailIds[i]);
			if (!LongUtils.isPrimaryKey(entity.getNoticeInventoryId())) {
				recieveNoticeInventoryService.updateRecieveNoticeInventory(entity);
			} else {
				recieveNoticeInventoryService.createRecieveNoticeInventory(entity);
			}
			// 再增加已存在的数量
			adjustFinanceBulkstockRecieve(entity.getBulkstockId(), entity.getQuantity(), BigDecimal.ZERO);
		}
	}

	@Transactional
	@Override
	public void cancelRecieveNotice(Long recieveNoticeId) {
		RecieveNoticeEntity entity = recieveNoticeService.inquireRecieveNoticeDetail(recieveNoticeId);
		FinanceApplicationEntity financeEntity = financeApplicationService.inquireFinanceApplicationEntity(entity.getFinanceId());
		if (NoticeStateEnum.UNCONFIRMED != entity.getNoticeState()) {
			throw new BusinessException("只能取消未确认的收货通知");
		}
		entity.setNoticeState(NoticeStateEnum.CANCEL);
		recieveNoticeService.updateRecieveNotice(entity);

		List<RecieveNoticeInventoryEntity> detailEntities = recieveNoticeInventoryService.inquireRecieveNoticeInventoryList(entity.getRecieveNoticeId());
		for (RecieveNoticeInventoryEntity de : detailEntities) {
			adjustFinanceBulkstockRecieve(de.getBulkstockId(), BigDecimal.ZERO, de.getQuantity());
		}

		// 项目状态更新
		financeEntity.setFinanceState(FinanceStateEnum.CONTRACT_SIGN);
		financeApplicationService.renovateFinanceApplication(financeEntity);
	}

	@Transactional
	@Override
	public void confirmRecieveNotice(Long recieveNoticeId) {
		RecieveNoticeEntity entity = recieveNoticeService.inquireRecieveNoticeDetail(recieveNoticeId);
		if (ProductTypeEnum.FREIGHT_FACTORING == entity.getProductType()) {
			entity.setNoticeState(NoticeStateEnum.FINISHED);
			entity.setConfirmAccount(FinanceSessionContext.getAccountFullName());
			entity.setConfirmAccountId(FinanceSessionContext.getAccountId());
			entity.setConfirmDateTime(new Date());
			recieveNoticeService.updateRecieveNotice(entity);

			FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(entity.getFinanceId());
			finance.setFinanceState(FinanceStateEnum.INSPECTIONED);
			financeApplicationService.updateFinanceApplication(finance);

			List<ContainerInventoryEntity> cies = containerInventoryService.inquireContainerInventoryList(finance.getFinanceId(), null);
			for (ContainerInventoryEntity cie : cies) {
				cie.setTallyDateTime(DateUtil.now());
				cie.setTallyingState(Boolean.TRUE);
				cie.setSupervisionState(SupervisionStateEnum.ALREADY_REPORT);
				cie.setRecieveNoticeId(recieveNoticeId);
				containerInventoryService.updateContainerInventory(cie);
			}
		} else {
			entity.setNoticeState(NoticeStateEnum.CONFIRMED);
			entity.setConfirmAccount(FinanceSessionContext.getAccountFullName());
			entity.setConfirmAccountId(FinanceSessionContext.getAccountId());
			entity.setConfirmDateTime(new Date());
			recieveNoticeService.updateRecieveNotice(entity);
		}
	}

	@Transactional
	@Override
	public void finishedRecieveNotice(Long recieveNoticeId) {
		RecieveNoticeEntity entity = recieveNoticeService.inquireRecieveNoticeDetail(recieveNoticeId);
		if (NoticeStateEnum.CONFIRMED != entity.getNoticeState()) {
			throw new BusinessException("请先确认该收货通知");
		}
		entity.setNoticeState(NoticeStateEnum.FINISHED);
		recieveNoticeService.updateRecieveNotice(entity);
	}

	@Override
	public RecieveNoticeDetail inquireRecieveNoticeDetail(Long recieveNoticeId) {
		RecieveNoticeEntity entity = recieveNoticeService.inquireRecieveNoticeDetail(recieveNoticeId);
		return BulkstockNoticeCastor.toRecieveNoticeDetail(entity);
	}

	@Override
	public PageList<RecieveNoticeDetail> inquireRecieveNoticePageList(Long financeId, String financeNumber, Integer noticeState, String enterpriseName, String bulkstockName, Integer productType, PageCriteria page) {
		Long logisticsCompanyId = null;
		if (FinanceSessionContext.isLogistics()) {
			logisticsCompanyId = FinanceSessionContext.getCompanyId();
		}
		PageList<RecieveNoticeEntity> pageList = recieveNoticeService.inquireRecieveNoticePageList(financeId, financeNumber, logisticsCompanyId, noticeState, enterpriseName, bulkstockName, productType, page);
		PageList<RecieveNoticeDetail> resultList = new PageList<>(page, pageList.getTotalRecordCount());
		for (RecieveNoticeEntity entity : pageList) {
			resultList.add(BulkstockNoticeCastor.toRecieveNoticeDetail(entity));
		}
		return resultList;
	}

	@Override
	public PageList<RecieveNoticeDetail> inquireRecieveNoticeLogisticsPageList(Long financeId, String financeNumber, Integer noticeState, PageCriteria page) {
		Long logisticsCompanyId = null;
		if (FinanceSessionContext.isLogistics()) {
			logisticsCompanyId = FinanceSessionContext.getCompanyId();
		}
		PageList<RecieveNoticeEntity> pageList = recieveNoticeService.inquireRecieveNoticeLogisticsPageList(financeId, financeNumber, logisticsCompanyId, noticeState, page);
		PageList<RecieveNoticeDetail> resultList = new PageList<>(page, pageList.getTotalRecordCount());
		for (RecieveNoticeEntity entity : pageList) {
			resultList.add(BulkstockNoticeCastor.toRecieveNoticeDetail(entity));
		}
		return resultList;
	}
	
	@Override
	public PageList<RecieveNoticeInventory> inquireRecieveNoticeBulkstockPageList(Long recieveNoticeId, PageCriteria page) {
		PageList<RecieveNoticeInventoryEntity> pageList = recieveNoticeInventoryService.inquireRecieveNoticePageList(recieveNoticeId, page);
		PageList<RecieveNoticeInventory> resultList = new PageList<>(page, pageList.getTotalRecordCount());
		for (RecieveNoticeInventoryEntity de : pageList) {
			RecieveNoticeInventory bulkstock = new RecieveNoticeInventory();
			BeanUtils.copyProperties(de, bulkstock);
			bulkstock.setRecieveNoticeDetailId(de.getNoticeInventoryId());
			resultList.add(bulkstock);
		}
		return resultList;
	}

	// =====================================================================================//
	@Transactional
	@Override
	public String createTransportNotice(Long financeId, String financeNumber, Long logisticsCompanyId, String logisticsCompanyName, String noticeRemark, Long[] inventoryIds) {
		TransportNoticeEntity entity = BulkstockNoticeCastor.fromTransportNotice(financeId, financeNumber, logisticsCompanyId, logisticsCompanyName, noticeRemark);
		FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(financeId);
		finance.setTransportNoticeCreateDatetime(null);
		Long transportNoticeId = transportNoticeService.createTransportNotice(entity);
		for (Long inventoryId : inventoryIds) {
			ContainerInventoryEntity inventory = containerInventoryService.inquireContainerInventory(inventoryId);
			inventory.setTransportCompanyId(logisticsCompanyId);
			inventory.setTransportNoticeId(transportNoticeId);
			containerInventoryService.updateContainerInventory(inventory);

			List<ContainerBulkstockEntity> containerBulkstockList = containerBulkstockService.inquireContainerBulkstockList(inventoryId);
			for (ContainerBulkstockEntity cbe : containerBulkstockList) {
				cbe.setTransportNoticeId(transportNoticeId);
				containerBulkstockService.renovateContainerBulkstock(cbe);
			}

			FinanceContainerLogEntity fcle = new FinanceContainerLogEntity();
			fcle.setInventoryId(inventory.getInventoryId());
			fcle.setOperator(FinanceSessionContext.getAccountFullName());
			fcle.setRemark("下发运输通知");
			financeContainerLogService.createFinanceContainerLog(fcle);
		}
		return transportNoticeId.toString();
	}

	@Transactional
	@Override
	public void updateTransportNotice(Long transportNoticeId, Long logisticsCompanyId, String logisticsCompanyName, String noticeRemark, Long[] inventoryIds) {
		TransportNoticeEntity persist = transportNoticeService.inquireTransportNoticeDetail(transportNoticeId);
		if (NoticeStateEnum.UNCONFIRMED != persist.getNoticeState()) {
			throw new BusinessException("只能修改未确认的运输通知");
		}
		TransportNoticeEntity entity = BulkstockNoticeCastor.fromTransportNotice(persist.getFinanceId(), persist.getFinanceNumber(), logisticsCompanyId, logisticsCompanyName, noticeRemark);
		entity.setTransportNoticeId(transportNoticeId);
		transportNoticeService.updateTransportNotice(entity);

		List<ContainerInventoryEntity> transportInventoryList = containerInventoryService.inquireTransportContainerInventoryList(transportNoticeId);
		Set<Long> inventoryIdSet = CollectionUtils.convertSet(inventoryIds);
		for (Long inventoryId : inventoryIds) {
			ContainerInventoryEntity inventory = containerInventoryService.inquireContainerInventory(inventoryId);
			inventory.setTransportCompanyId(logisticsCompanyId);
			inventory.setTransportNoticeId(transportNoticeId);
			containerInventoryService.updateContainerInventory(inventory);
			List<ContainerBulkstockEntity> containerBulkstockList = containerBulkstockService.inquireContainerBulkstockList(inventoryId);
			for (ContainerBulkstockEntity cbe : containerBulkstockList) {
				cbe.setTransportNoticeId(transportNoticeId);
				containerBulkstockService.renovateContainerBulkstock(cbe);
			}
		}
		for (ContainerInventoryEntity cie : transportInventoryList) {
			if (!inventoryIdSet.contains(cie.getInventoryId())) {
				cie.setTransportCompanyId(null);
				cie.setTransportNoticeId(null);
				containerInventoryService.renovateContainerInventory(cie);

				List<ContainerBulkstockEntity> containerBulkstockList = containerBulkstockService.inquireContainerBulkstockList(cie.getInventoryId());
				for (ContainerBulkstockEntity cbe : containerBulkstockList) {
					cbe.setTransportNoticeId(null);
					containerBulkstockService.renovateContainerBulkstock(cbe);
				}
			}
		}
	}

	@Transactional
	@Override
	public void cancelTransportNotice(Long transportNoticeId) {
		TransportNoticeEntity entity = transportNoticeService.inquireTransportNoticeDetail(transportNoticeId);
		if (NoticeStateEnum.UNCONFIRMED != entity.getNoticeState()) {
			throw new BusinessException("只能取消未确认的运输通知");
		}
		entity.setNoticeState(NoticeStateEnum.CANCEL);
		transportNoticeService.updateTransportNotice(entity);

		List<ContainerBulkstockEntity> containerBulkstockList = containerBulkstockService.inquireTransportContainerBulkstockList(transportNoticeId);
		for (ContainerBulkstockEntity cbe : containerBulkstockList) {
			ContainerInventoryEntity inventory = containerInventoryService.inquireContainerInventory(cbe.getInventoryId());
			inventory.setTransportCompanyId(null);
			inventory.setTransportNoticeId(null);
			containerInventoryService.renovateContainerInventory(inventory);
			cbe.setTransportNoticeId(null);
			containerBulkstockService.renovateContainerBulkstock(cbe);
		}
	}

	@Transactional
	@Override
	public void confirmTransportNotice(Long transportNoticeId) {
		TransportNoticeEntity entity = transportNoticeService.inquireTransportNoticeDetail(transportNoticeId);
		if (NoticeStateEnum.UNCONFIRMED != entity.getNoticeState()) {
			throw new BusinessException("只能确认的未确认运输通知");
		}
		entity.setNoticeState(NoticeStateEnum.CONFIRMED);
		entity.setConfirmAccount(FinanceSessionContext.getAccountFullName());
		entity.setConfirmAccountId(FinanceSessionContext.getAccountId());
		entity.setConfirmDateTime(new Date());
		transportNoticeService.updateTransportNotice(entity);

		List<ContainerInventoryEntity> transportInventoryList = containerInventoryService.inquireTransportContainerInventoryList(transportNoticeId);
		for (ContainerInventoryEntity inventory : transportInventoryList) {
			List<ContainerBulkstockEntity> containerBulkstockList = containerBulkstockService.inquireContainerBulkstockList(inventory.getInventoryId());
			for (ContainerBulkstockEntity cbe : containerBulkstockList) {
				cbe.setTransportNoticeId(cbe.getTransportNoticeId());
				containerBulkstockService.renovateContainerBulkstock(cbe);
			}
		}

		// 发送消息
		FinanceLetterBlockingQueue.putEnterpriseFinanceLetter(getFinanceEnterpriseId(entity.getFinanceId()), "运输通知", "finance.transport.notice", entity.getTransportNoticeNumber());

		// 项目动态
		FinanceProcessEntity processEntity = FinanceProcessCastor.fromFinanceTransportProcess(entity);
		if (!LongUtils.isPrimaryKey(processEntity.getProcessId())) {
			financeProcessService.createFinanceProcess(processEntity);
		} else {
			financeProcessService.renovateFinanceProcess(processEntity);
		}
		for (FinanceProcessDetailEntity fpd : processEntity.getCurrentDetails()) {
			fpd.setProcessId(processEntity.getProcessId());
			financeProcessDetailService.createFinanceProcessDetail(fpd);
		}
	}

	@Transactional
	@Override
	public void finishedTransportNotice(Long transportNoticeId, String shipsName, String voyageNumber, Date harborDateTime, String harbor, String fileUuid) {
		TransportNoticeEntity entity = transportNoticeService.inquireTransportNoticeDetail(transportNoticeId);
		FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(entity.getFinanceId());
		finance.setTransportNoticeCreateDatetime(null);
		financeApplicationService.renovateFinanceApplication(finance);

		if (NoticeStateEnum.CONFIRMED != entity.getNoticeState()) {
			throw new BusinessException("请先确认该运输通知");
		}
		entity.setNoticeState(NoticeStateEnum.FINISHED);
		//		entity.setShipsName(shipsName);
		//		entity.setVoyageNumber(voyageNumber);
		//		entity.setHarborDateTime(harborDateTime);
		//		entity.setHarbor(harbor);
		entity.setFileUuid(fileUuid);
		transportNoticeService.updateTransportNotice(entity);

		List<ContainerInventoryEntity> inventoryList = containerInventoryService.inquireTransportContainerInventoryList(transportNoticeId);
		for (ContainerInventoryEntity cie : inventoryList) {
			cie.setHarborState(Boolean.TRUE);
			//			cie.setShipsName(shipsName);
			//			cie.setVoyageNumber(voyageNumber);
			//			cie.setHarborDateTime(harborDateTime);
			//			cie.setHarbor(harbor);
			cie.setFileUuid(fileUuid);
			containerInventoryService.renovateContainerInventory(cie);

			FinanceContainerLogEntity fcle = new FinanceContainerLogEntity();
			fcle.setInventoryId(cie.getInventoryId());
			fcle.setOperator(entity.getLogisticsCompanyName());
			fcle.setRemark("到港");
			financeContainerLogService.createFinanceContainerLog(fcle);
		}
		financeBulkstockService.calculateHarborFinanceBulkstock(entity.getFinanceId());

		// 发送消息
		FinanceLetterBlockingQueue.putEnterpriseFinanceLetter(getFinanceEnterpriseId(entity.getFinanceId()), "运输通知", "finance.transport.finished", entity.getTransportNoticeNumber());

		// 项目动态
		FinanceProcessEntity processEntity = FinanceProcessCastor.fromFinanceArriveProcess(entity);
		if (!LongUtils.isPrimaryKey(processEntity.getProcessId())) {
			financeProcessService.createFinanceProcess(processEntity);
		} else {
			financeProcessService.renovateFinanceProcess(processEntity);
		}
	}

	@Override
	@Transactional
	public void saveTransportInfo(Long[] inventoryId, String shipsName, String voyageNumber, Date harborDateTime, String harbor) {
		List<ContainerInventoryEntity> inventoryList = containerInventoryService.inquireContainerInventoryList(inventoryId);
		for (ContainerInventoryEntity cie : inventoryList) {
			cie.setShipsName(shipsName);
			cie.setVoyageNumber(voyageNumber);
			cie.setHarborDateTime(harborDateTime);
			cie.setHarbor(harbor);
			cie.setHarborState(Boolean.TRUE);
			containerInventoryService.renovateContainerInventory(cie);
		}
	}

	@Override
	public TransportNoticeDetail inquireTransportNoticeDetail(Long transportNoticeId) {
		TransportNoticeEntity entity = transportNoticeService.inquireTransportNoticeDetail(transportNoticeId);
		return BulkstockNoticeCastor.toTransportNoticeDetail(entity);
	}

	@Override
	@Transactional
	public PageList<TransportNoticeLineInfo> inquireTransportNoticePageList(Long financeId, String financeNumber, String dateBegin, String dateEnd, Integer noticeState, String enterpriseName, String bulkstockName, Integer productType, PageCriteria page) {
		Long logisticsCompanyId = null;
		if (FinanceSessionContext.isLogistics()) {
			logisticsCompanyId = FinanceSessionContext.getCompanyId();
		}
		Date beginDate = DateUtils.formatBeginDay(dateBegin);
		Date endDate = DateUtils.formatEndDay(dateEnd);
		
		List<Long> financeIds= financeApplicationService.getFinanceListIds2(productType,enterpriseName);
		PageList<TransportNoticeEntity> pageList = transportNoticeService.inquireTransportNoticePageLists(financeIds, financeId, financeNumber, logisticsCompanyId, beginDate, endDate, noticeState,bulkstockName, page);
		PageList<TransportNoticeLineInfo> resultList = new PageList<TransportNoticeLineInfo>(page, pageList.getTotalRecordCount());
		for (TransportNoticeEntity entity : pageList) {
			resultList.add(BulkstockNoticeCastor.toTransportNoticeLineInfo(entity));
		}
		return resultList;
	}

	// =======================================================================================================================================================//
	@Transactional
	@Override
	public String createDeliveryNotice(Long pickupId, Long[] inventoryIds, Long logisticsCompanyId, String noticeRemark) {
		PickupApplicationEntity pickup = pickupApplicationService.inquirePickupApplication(pickupId);
		pickup.setDeliveryNoticeCreateDateTime(null);

		if (ApplicationStateEnum.RECEIPT != pickup.getApplicationState() && ExchangeStatusEnum.FINISHED != pickup.getExchangeStatus()) {
			throw new BusinessException("已收款的提货单才能下发放货通知");
		}
		DeliveryNoticeEntity deliveryNotice = BulkstockNoticeCastor.fromDeliveryNotice(pickup, logisticsCompanyId, noticeRemark);
		List<ContainerInventoryEntity> cies = containerInventoryService.inquireContainerInventoryList(inventoryIds);
		for (ContainerInventoryEntity cie : cies) {
			if (cie.getDeliveryNoticeId() != null) {
				throw new BusinessException("箱号[" + cie.getCaseNumber() + "]已下发放货通知");
			}
			//解锁
			if (cie.getLogisticsCompanyInfoId() != 1L) {
				continue;
			}
			HandleSuitcaseResult result = financeApplicationActionApi.goldUnlocked(cie.getWaybillNumber(), cie.getCaseNumber());
			FinanceContainerLogEntity fcle = new FinanceContainerLogEntity();
			fcle.setInventoryId(cie.getInventoryId());
			fcle.setOperator(FinanceSessionContext.getAccountFullName());
			if (result != null) {
				fcle.setRemark("解锁 " + result.getMessage());
			} else {
				fcle.setRemark("解锁 ");
			}
			financeContainerLogService.createFinanceContainerLog(fcle);
			//			logger.info("Message" + result.getMessage() + ",result" + result.getResult());
		}
		if (PickupMethodEnum.CASH_DELIVERY != pickup.getPickupMethod()) { // 换货换箱类型,校验放货箱融资总额 <= 换货换箱进来的已经监管的融资总额
			List<ContainerInventoryEntity> targets = containerInventoryService.inquireExchangeContainerInventoryList(pickup.getPickupId());
			//			BigDecimal financeAmount = BigDecimal.ZERO;
			for (ContainerInventoryEntity cie : targets) {
				if (SupervisionStateEnum.ALREADY_SUPERVISE != cie.getSupervisionState() && SupervisionStateEnum.RELIEVE_SUPERVISE != cie.getSupervisionState()) { // 未进入监管不计算
					throw new BusinessException("新货箱还未进入监管！");
					//					continue;
				}
				//				financeAmount = financeAmount.add(BulkstockCastor.caculateFinanceAmount(cie));
			}
			List<ContainerInventoryEntity> sources = containerInventoryService.inquirePickupContainerInventoryList(pickup.getPickupId());
			for (ContainerInventoryEntity cie : sources) {
				boolean exists = false;
				for (ContainerInventoryEntity delivery : cies) {
					if (cie.getInventoryId().equals(delivery.getInventoryId())) { // 本次放货箱
						//						financeAmount = financeAmount.subtract(BulkstockCastor.caculateFinanceAmount(cie));
						exists = true;
						break;
					}
				}
				if (exists) { // 本次放货已计算过
					continue;
				}
				if (cie.getDeliveryNoticeId() != null) { // 已经下发放货通知
					//					financeAmount = financeAmount.subtract(BulkstockCastor.caculateFinanceAmount(cie));
				}
			}
			//TODO 有问题
			//			if (financeAmount.compareTo(BigDecimal.ZERO) == -1) { // 换箱换货进来的箱所对应的融资总额 < 该提货申请所放箱的融资总额
			//				throw new BusinessException("下发放货通知的箱总额超过所置换的监管箱总额");
			//			}
		}

		Long deliveryNoticeId = deliveryNoticeService.createDeliveryNotice(deliveryNotice);
		for (ContainerInventoryEntity cie : cies) {
			cie.setDeliveryNoticeId(deliveryNoticeId);
			containerInventoryService.renovateContainerInventory(cie);
		}

		// 是否全部下发放货
		boolean release = true;
		cies = containerInventoryService.inquirePickupContainerInventoryList(pickupId);
		for (ContainerInventoryEntity cie : cies) {
			if (cie.getDeliveryNoticeId() == null) {
				release = false;
				break;
			}
		}
		if (release) {
			pickup.setApplicationState(ApplicationStateEnum.RELEASE);
			pickupApplicationService.renovatePickupApplication(pickup);
		}
		FinanceApplicationEntity financeEntity = financeApplicationService.inquireFinanceApplicationEntity(pickup.getFinanceId());
		financeEntity.setFinanceState(FinanceStateEnum.PUTGOOD);
		financeApplicationService.renovateFinanceApplication(financeEntity);
		// 项目动态
		FinanceProcessDetailEntity processDetailEntity = FinanceProcessCastor.fromFinancePickupDeliveryNoticeProcessDetail(deliveryNotice);
		financeProcessDetailService.createFinanceProcessDetail(processDetailEntity);
		return deliveryNoticeId.toString();
	}
	
	@Override
	@Transactional
	public void autoDeliveryInventory(Long pickupId) {
		PickupApplicationEntity pickup = pickupApplicationService.inquirePickupApplication(pickupId);
		pickup.setApplicationState(ApplicationStateEnum.RELEASE);
		List<ContainerInventoryEntity> inventories = containerInventoryService.inquirePickupContainerInventoryList(pickupId);
		for (ContainerInventoryEntity cie : inventories) {
			cie.setSupervisionState(SupervisionStateEnum.RELIEVE_SUPERVISE);
			containerInventoryService.updateContainerInventory(cie);
			
			FinanceContainerLogEntity fcle = new FinanceContainerLogEntity();
			fcle.setInventoryId(cie.getInventoryId());
			fcle.setOperator(FinanceSessionContext.getAccountFullName());
			fcle.setRemark("放货 解除监管");
			financeContainerLogService.createFinanceContainerLog(fcle);
		}
		pickupApplicationService.updatePickupApplication(pickup);
	}

	@Transactional
	@Override
	public void cancelDeliveryNotice(Long deliveryNoticeId) {
		DeliveryNoticeEntity entity = deliveryNoticeService.inquireDeliveryNoticeDetail(deliveryNoticeId);
		if (NoticeStateEnum.UNCONFIRMED != entity.getNoticeState()) {
			throw new BusinessException("只能取消未确认的放货通知");
		}
		entity.setNoticeState(NoticeStateEnum.CANCEL);
		StringBuffer sb = new StringBuffer("取消箱信息如下：");
		List<ContainerInventoryEntity> cies = containerInventoryService.inquireDeliveryNoticeContainerInventoryList(deliveryNoticeId);
		for (ContainerInventoryEntity cie : cies) {
			sb.append(cie.getCaseNumber()).append("(").append(cie.getWaybillNumber()).append(")").append(";");
			cie.setDeliveryNoticeId(null);
			containerInventoryService.renovateContainerInventory(cie);
		}
		entity.setCancelRemark(sb.toString());
		deliveryNoticeService.renovateDeliveryNotice(entity);

		FinanceApplicationEntity financeEntity = financeApplicationService.inquireFinanceApplicationEntity(entity.getFinanceId());
		financeEntity.setFinanceState(FinanceStateEnum.WAIT_PUTGOOD);
		financeApplicationService.renovateFinanceApplication(financeEntity);
	}

	@Transactional
	@Override
	public void confirmDeliveryNotice(Long deliveryNoticeId) {
		DeliveryNoticeEntity entity = deliveryNoticeService.inquireDeliveryNoticeDetail(deliveryNoticeId);
		if (NoticeStateEnum.UNCONFIRMED != entity.getNoticeState()) {
			throw new BusinessException("只能确认的未确认放货通知");
		}
		entity.setNoticeState(NoticeStateEnum.CONFIRMED);
		entity.setConfirmAccount(FinanceSessionContext.getAccountFullName());
		entity.setConfirmAccountId(FinanceSessionContext.getAccountId());
		entity.setConfirmDateTime(new Date());
		deliveryNoticeService.updateDeliveryNotice(entity);

		// 发送消息
		FinanceLetterBlockingQueue.putEnterpriseFinanceLetter(getFinanceEnterpriseId(entity.getFinanceId()), "放货通知", "finance.delivery.notice", entity.getDeliveryNoticeNumber());
	}

	@Transactional
	@Override
	public void finishedDeliveryNotice(Long deliveryNoticeId) {
		DeliveryNoticeEntity entity = deliveryNoticeService.inquireDeliveryNoticeDetail(deliveryNoticeId);
		if (NoticeStateEnum.CONFIRMED != entity.getNoticeState()) {
			throw new BusinessException("请先确认该放货通知");
		}
		entity.setNoticeState(NoticeStateEnum.FINISHED);
		deliveryNoticeService.updateDeliveryNotice(entity);
	}

	@Override
	public DeliveryNoticeDetail inquireDeliveryNoticeDetail(Long deliveryNoticeId) {
		DeliveryNoticeEntity entity = deliveryNoticeService.inquireDeliveryNoticeDetail(deliveryNoticeId);
		return BulkstockNoticeCastor.toDeliveryNoticeDetail(entity);
	}
	
	@Transactional
	@Override
	public PageList<DeliveryNoticeLineInfo> inquireDeliveryNoticePageList(Long financeId, String logisticsCompanyName, String financeNumber, Integer noticeState,String enterpriseName, String bulkstockName, Integer productType, PageCriteria page) {
		Long logisticsCompanyId = null;
		if (FinanceSessionContext.isLogistics()) {
			logisticsCompanyId = FinanceSessionContext.getCompanyId();
		}
		List<Long> financeIds = financeApplicationService.getFinanceListIds2(productType,enterpriseName);
		PageList<DeliveryNoticeEntity> pageList = deliveryNoticeService.inquireDeliveryNoticePageLists(financeIds,financeId, logisticsCompanyName, financeNumber, logisticsCompanyId, noticeState,bulkstockName, page);
		PageList<DeliveryNoticeLineInfo> resultList = new PageList<>(page, pageList.getTotalRecordCount());
		for (DeliveryNoticeEntity entity : pageList) {
			resultList.add(BulkstockNoticeCastor.toDeliveryNoticeLineInfo(entity));
		}
		return resultList;
	}
}
